import { reactive, computed, provide, inject } from 'vue';

class Store {
  constructor (options) {
    const state = options.state;
    const mutations = options.mutations;
    const actions = options.actions;
    const getters = options.getters;

    const store = this;
    store._state = reactive({ data: state });

    // 防止用户在调用的时候 误操作使用到不属于mutations本身的属性
    store._mutations = Object.create(null);
    store._actions = Object.create(null);
    store.getters = {}
    // mutations = {
    //   addTodo(state, payload) {

    //   },
    //   removeTodo(state, payload) {

    //   }
    // }
    // store._mutations['addTodo'] = () => {

    // }

    Object.keys(mutations).forEach(key => {
      store._mutations[key] = (payload) => {
        mutations[key](store._state.data, payload)
      }
    })

    // actions = {
    //   addTodo(store, payload) {

    //   },
    //   removeTodo(store, payload) {

    //   }
    // }

    Object.keys(actions).forEach(key => {
      store._actions[key] = (payload) => {
        actions[key](store, payload)
      }
    })

    // getters = {
    //   allTodo(state, getters) {
    //     return state.todos;
    //   },
    //   finished(state, getters) {
    //     return state.todos.filter(todo => todo.isFinished);
    //   }
    // }

    Object.keys(getters).forEach(key => {
      Object.defineProperty(this.getters, key, {
        get: () => computed(() => getters[key](store._state.data, store.getters)).value
      })
    })
  }

  get state () {
    return this._state.data;
  }

  commit (type, payload) {
    store._mutations[type](payload)
  }
  
  dispatch (type, payload) {
    store._actions[type](payload)

  }

  install (app) {
    app.provide('store', this);
    app.config.globalProperties.$store = this;
  }
}

export function createStore(options) {
  return new Store(options)
}

export function useStore() {
  return inject('store')
}